import { BeforeOpenModalResult, ElementPropertyConfig, KeyMap, PropertyEntity } from '@farris/ide-property-panel';
import { BindingCustomEditorComponent, BindingCustomType, BindingCustomEditorConverter } from '@farris/designer-devkit';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import { InputProps } from '../../common/property/input-property-config';
import { DATE_FORMATS } from './date-format';

export class DateBoxProp extends InputProps {


    propertyConfig: ElementPropertyConfig[];

    getPropConfig(propertyData: any): ElementPropertyConfig[] {

        this.propertyConfig = [];

        // 基本信息属性
        const basicPropConfig = this.getBasicPropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(basicPropConfig);

        // 外观属性
        const appearanceProperties = this.getAppearancePropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(appearanceProperties);

        // 行为属性
        const behaviorPropConfig = this.getBehaviorPropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(behaviorPropConfig);

        // 扩展区域属性
        // const appendPropConfig = this.getInputAppendPropertyConfig(propertyData, this.viewModelId);
        // this.propertyConfig.push(appendPropConfig);

        // 表达式属性
        const exprPropConfig = this.getExpressionPropConfig(propertyData, this.viewModelId);
        if (exprPropConfig) {
            this.propertyConfig.push(exprPropConfig);
        }

        // 事件属性
        const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(eventPropConfig);

        return this.propertyConfig;
    }

    public getBasicPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {

        const basicProperties = this.getBasicCommonPropConfig(propertyData);
        basicProperties.push(
            {
                propertyID: 'controlSource',
                propertyName: '控件来源',
                propertyType: 'select',
                description: '组件的控件来源',
                iterator: [{ key: 'Farris', value: 'Farris' }, { key: 'Kendo', value: 'Kendo' }],
                refreshPanelAfterChanged: true,
                visible: showPosition === 'card' && propertyData.controlSource !== 'Farris'
            }
        );
        const self = this;
        return {
            categoryId: 'basic',
            categoryName: '基本信息',
            properties: basicProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {

                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'type': {
                        self.changeControlType(propertyData, changeObject.propertyValue);
                        break;
                    }
                    case 'controlSource': {

                        // 变更【外观分类】下的属性
                        const newAppearancePropConfig = self.getAppearancePropConfig(propertyData, viewModelId);
                        const currentAppearanceConfig = self.propertyConfig.find(cat => cat.categoryId === 'appearance');
                        Object.assign(currentAppearanceConfig, newAppearancePropConfig);

                        // 变更【行为分类】下的属性
                        const newBehaviorPropConfig = self.getBehaviorPropConfig(propertyData, viewModelId);
                        const currentBehaviorConfig = self.propertyConfig.find(cat => cat.categoryId === 'behavior');
                        Object.assign(currentBehaviorConfig, newBehaviorPropConfig);

                    }
                }

            },

        };

    }

    private getAppearancePropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {

        let appearanceProperties = [];
        if (showPosition === 'card' || showPosition === 'tableTdEditor') {
            const appearanceCommonProps = this.getAppearanceCommonPropConfig(propertyData, viewModelId, showPosition);
            appearanceProperties = appearanceProperties.concat(appearanceCommonProps);
        }

        const dateBoxAppearanceProps = this.getDateBoxAppearanceProps(propertyData);
        appearanceProperties = appearanceProperties.concat(dateBoxAppearanceProps);

        const self = this;
        const config = {
            categoryId: 'appearance',
            categoryName: '外观',
            properties: appearanceProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {

                if (!changeObject) {
                    return;
                }
                self.changeAppearancePropertyRelates(this.properties, changeObject, propertyData, parameters);
            },

        };

        if (showPosition !== 'card') {
            Object.assign(config, {
                categoryId: showPosition + '_' + config.categoryId,
                propertyData,
                enableCascade: true,
                parentPropertyID: 'editor',
                tabId: showPosition,
                tabName: '编辑器'
            });
        }
        return config;
    }

    private getDateBoxAppearanceProps(propertyData: any) {
        const controlSource = propertyData.controlSource;
        return [
            {
                propertyID: 'dateFormat',
                propertyName: '日期格式化',
                propertyType: 'select',
                description: '日期格式化方式选择',
                controlSource: 'Farris',
                visible: controlSource === 'Farris',
                iterator: this.getDateFormatIteratror(propertyData)
            }
        ];
    }

    private getBehaviorPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {

        const controlSource = propertyData.controlSource;

        let behaviorProperties: PropertyEntity[] = [];
        if (showPosition === 'card' || showPosition === 'tableTdEditor') {
            behaviorProperties = this.getBehaviorCommonPropConfig(propertyData, viewModelId);
        }
        behaviorProperties.push(
            {
                propertyID: 'maxValue',
                propertyName: '最大值',
                propertyType: 'modal',
                editor: BindingCustomEditorComponent,
                editorParams: {
                    modalTitle: '最大值编辑器',
                    viewModelId,
                    customType: propertyData.showTime ? BindingCustomType.datetime : BindingCustomType.date,
                    minDate: propertyData.minValue && typeof propertyData.minValue === 'string' ? propertyData.minValue : undefined
                },
                converter: new BindingCustomEditorConverter(),
                beforeOpenModal(): BeforeOpenModalResult {
                    // 取参数最新值:最小值为固定日期时才进行限制
                    this.editorParams.minDate = propertyData.minValue && typeof propertyData.minValue === 'string' ? propertyData.minValue : undefined;
                    return { result: true, message: '' };
                }
            },
            {
                propertyID: 'minValue',
                propertyName: '最小值',
                propertyType: 'modal',
                editor: BindingCustomEditorComponent,
                editorParams: {
                    modalTitle: '最小值编辑器',
                    viewModelId,
                    customType: propertyData.showTime ? BindingCustomType.datetime : BindingCustomType.date,
                    maxDate: propertyData.maxValue && typeof propertyData.maxValue === 'string' ? propertyData.maxValue : undefined
                },
                converter: new BindingCustomEditorConverter(),
                beforeOpenModal(): BeforeOpenModalResult {
                    // 取参数最新值

                    this.editorParams.maxDate = propertyData.maxValue && typeof propertyData.maxValue === 'string' ? propertyData.maxValue : undefined;
                    return { result: true, message: '' };
                }
            },
            {
                propertyID: 'format',
                propertyName: '格式',
                propertyType: 'select',
                description: '日期格式选择',
                iterator: [
                    { key: '\'yyyy-MM-dd\'', value: 'yyyy-MM-dd' },
                    { key: '\'yyyy/MM/dd\'', value: 'yyyy/MM/dd' },
                    { key: '\'yyyy年MM月dd日\'', value: 'yyyy年MM月dd日' }],
                controlSource: 'Kendo',
                visible: controlSource === 'Kendo'
            },
            {
                propertyID: 'editable',
                propertyName: '允许输入',
                propertyType: 'select',
                description: '是否允许手动输入日期',
                controlSource: 'Farris',
                visible: controlSource === 'Farris',
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }]
            },
            {
                propertyID: 'dateRange',
                propertyName: '使用日期范围模式',
                propertyType: 'select',
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }],
                description: '是否使用日期范围模式',
                controlSource: 'Farris',
                visible: controlSource === 'Farris' && propertyData.fieldType === 'String' && showPosition === 'card',
                refreshPanelAfterChanged: true
            },
            {
                propertyID: 'dateRangeDatesDelimiter',
                propertyName: '日期分隔符',
                propertyType: 'string',
                description: '日期分隔符设置',
                controlSource: 'Farris',
                visible: propertyData.dateRange && controlSource === 'Farris' && showPosition === 'card'
            },
            {
                propertyID: 'showType',
                propertyName: '显示类型',
                propertyType: 'select',
                description: '日期显示类型选择',
                iterator: this.getShowTypeIterator(propertyData),
                controlSource: 'Farris',
                visible: controlSource === 'Farris',
                refreshPanelAfterChanged: true
            },
            {
                propertyID: 'showTime',
                propertyName: '启用时间选择',
                propertyType: 'select',
                description: '是否启用时间选择',
                controlSource: 'Farris',
                visible: controlSource === 'Farris' && propertyData.fieldType !== 'Date' &&
                    (propertyData.showType === 1 || propertyData.showType === 4),
                refreshPanelAfterChanged: true,
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }]
            },
            {
                propertyID: 'returnFormat',
                propertyName: '存储格式',
                propertyType: 'select',
                description: '存储格式选择',
                controlSource: 'Farris',
                visible: controlSource === 'Farris' && propertyData.fieldType === 'String',
                iterator: this.getReturnFormatIteratror()
            },
            {
                propertyID: 'showWeekNumbers',
                propertyName: '显示第几周',
                propertyType: 'select',
                description: '是否显示第几周',
                controlSource: 'Farris',
                visible: controlSource === 'Farris',
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }]
            },
            {
                propertyID: 'useDefault',
                propertyName: '使用默认值',
                propertyType: 'select',
                description: '是否使用默认值',
                visible: propertyData.binding && propertyData.binding.type !== 'Form' && controlSource === 'Farris',
                controlSource: 'Farris',
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }]
            },
            {
                propertyID: 'localization',
                propertyName: '启用数据国际化',
                propertyType: 'select',
                description: '是否启用数据国际化',
                visible: controlSource === 'Farris' && showPosition === 'card',
                controlSource: 'Farris',
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }]
            },
            {
                propertyID: 'localizationType',
                propertyName: '数据国际化类型',
                propertyType: 'select',
                description: '数据国际化类型选择',
                visible: controlSource === 'Farris' && showPosition === 'card' && propertyData.localization,
                controlSource: 'Farris',
                iterator: this.getLocalizationTypes(propertyData)
            },
            {
                propertyID: 'firstDayOfWeek',
                propertyName: '每周起始日',
                propertyType: 'select',
                description: '每周起始日',
                iterator: [{ key: 'mo', value: '星期一' }, { key: 'su', value: '星期日' }]
            },
            {
                propertyID: 'hourStep',
                propertyName: '时步长',
                propertyType: 'number',
                description: '时步长设置',
                decimals: 0,
                min: 1,
                visible: propertyData.showTime,
            },
            {
                propertyID: 'minuteStep',
                propertyName: '分步长',
                propertyType: 'number',
                description: '分步长设置',
                decimals: 0,
                min: 1,
                visible: propertyData.showTime,
            },
            {
                propertyID: 'secondStep',
                propertyName: '秒步长',
                propertyType: 'number',
                description: '秒步长设置',
                decimals: 0,
                min: 1,
                visible: propertyData.showTime,
            }
        );

        const self = this;
        const config = {
            categoryId: 'behavior',
            categoryName: '行为',
            properties: behaviorProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, data, parameters) {
                if (!changeObject) {
                    return;
                }
                self.changeBehaviorPropertyRelates(this.properties, changeObject, propertyData, parameters, showPosition);

                switch (changeObject && changeObject.propertyID) {
                    case 'editType': {
                        const dialogWidth = this.properties.find(p => p.propertyID === 'dialogWidth');
                        if (dialogWidth) {
                            dialogWidth.visible = changeObject.propertyValue === 'dialog';
                        }
                        const dialogHeight = this.properties.find(p => p.propertyID === 'dialogHeight');
                        if (dialogHeight) {
                            dialogHeight.visible = changeObject.propertyValue === 'dialog';
                        }
                        break;
                    }
                    case 'dateRange': {
                        const delimiterProp = this.properties.find(p => p.propertyID === 'dateRangeDatesDelimiter');
                        if (delimiterProp) {
                            delimiterProp.visible = changeObject.propertyValue;
                        }
                        // 关闭日期范围模式时，显示类型不能配置成"周选择"
                        const showType = this.properties.find(p => p.propertyID === 'showType');
                        if (showType) {
                            showType.iterator = self.getShowTypeIterator(propertyData);
                            if (!changeObject.propertyValue && propertyData.showType === 4) {
                                propertyData.showType = 1;
                            }
                        }
                        // 重新获取日期格式枚举项
                        const appearanceConfig = self.propertyConfig.find(c => c.categoryId.includes('appearance'));
                        if (appearanceConfig) {
                            const dateFormat = appearanceConfig.properties.find(p => p.propertyID === 'dateFormat');
                            if (dateFormat) {
                                dateFormat.iterator = self.getDateFormatIteratror(propertyData);
                            }
                        }

                        changeObject.relateChangeProps = [{
                            propertyID: 'dateFormat',
                            propertyValue: propertyData.dateFormat
                        },
                        {
                            propertyID: 'showType',
                            propertyValue: propertyData.showType
                        },
                        {
                            propertyID: 'showTime',
                            propertyValue: propertyData.showTime
                        }];
                        break;
                    }
                    case 'maxValue': {
                        const minProp = this.properties.find(p => p.propertyID === 'minValue');
                        if (minProp) {
                            minProp.max = changeObject.propertyValue ? changeObject.propertyValue : undefined;
                        }
                        break;
                    }
                    case 'minValue': {
                        const maxProp = this.properties.find(p => p.propertyID === 'maxValue');
                        if (maxProp) {
                            maxProp.min = changeObject.propertyValue ? changeObject.propertyValue : undefined;
                        }
                        break;
                    }
                    case 'showType': {
                        // 切换显示类型时对应修改日期格式
                        switch (changeObject.propertyValue) {
                            case 1: case 4: {
                                propertyData.dateFormat = 'yyyy-MM-dd';
                                break;
                            }
                            case 2: {
                                propertyData.dateFormat = 'yyyy-MM';
                                propertyData.showTime = false;
                                break;
                            }
                            case 3: {
                                propertyData.dateFormat = 'yyyy';
                                propertyData.showTime = false;
                                break;
                            }
                        }

                        // 显示类型为全部时 才可以启用时间选择
                        const showTime = this.properties.find(p => p.propertyID === 'showTime');
                        if (showTime) {
                            showTime.visible = (changeObject.propertyValue === 1 || changeObject.propertyValue === 4) &&
                                propertyData.fieldType !== 'Date';
                        }
                        // 时间步长属性
                        const timeProps = this.properties.filter(p => ['hourStep', 'minuteStep', 'secondStep'].includes(p.propertyID));
                        if (timeProps && timeProps.length) {
                            timeProps.forEach(t => t.visible = propertyData.showTime && showTime.visible);

                        }
                        // 重新获取日期格式枚举项
                        const appearanceConfig = self.propertyConfig.find(c => c.categoryId.includes('appearance'));
                        if (appearanceConfig) {
                            const dateFormat = appearanceConfig.properties.find(p => p.propertyID === 'dateFormat');
                            if (dateFormat) {
                                dateFormat.iterator = self.getDateFormatIteratror(propertyData);
                            }
                        }

                        changeObject.relateChangeProps = [{
                            propertyID: 'dateFormat',
                            propertyValue: propertyData.dateFormat
                        },
                        {
                            propertyID: 'showTime',
                            propertyValue: propertyData.showTime
                        }];
                        break;
                    }

                    case 'localization': {
                        const localizationType = this.properties.find(p => p.propertyID === 'localizationType');
                        if (localizationType) {
                            localizationType.visible = changeObject.propertyValue;
                        }
                        break;
                    }
                    case 'showTime': {
                        const appearanceConfig = self.propertyConfig.find(c => c.categoryId.includes('appearance'));
                        if (appearanceConfig) {
                            const dateFormat = appearanceConfig.properties.find(p => p.propertyID === 'dateFormat');
                            if (dateFormat) {
                                dateFormat.iterator = self.getDateFormatIteratror(propertyData);

                                if (changeObject.propertyValue) {
                                    propertyData.dateFormat = 'yyyy-MM-dd HH:mm:ss';
                                    propertyData.returnFormat = 'yyyy-MM-dd HH:mm:ss';
                                } else {
                                    propertyData.dateFormat = 'yyyy-MM-dd';
                                    propertyData.returnFormat = 'yyyy-MM-dd';
                                }
                            }
                        }


                        changeObject.relateChangeProps = [{
                            propertyID: 'dateFormat',
                            propertyValue: propertyData.dateFormat
                        },
                        {
                            propertyID: 'returnFormat',
                            propertyValue: propertyData.returnFormat
                        }];


                        // 联动修改最大值最小值属性的参数
                        const maxMinProps = this.properties.filter(p => p.propertyID === 'maxValue' || p.propertyID === 'minValue');
                        if (maxMinProps.length) {
                            maxMinProps.forEach(prop => {
                                prop.editorParams.customType = changeObject.propertyValue ? BindingCustomType.datetime : BindingCustomType.date;
                            });
                        }

                        // 时间步长属性
                        const timeProps = this.properties.filter(p => ['hourStep', 'minuteStep', 'secondStep'].includes(p.propertyID));
                        if (timeProps && timeProps.length) {
                            timeProps.forEach(t => t.visible = changeObject.propertyValue);

                        }
                        break;
                    }
                }
            }

        };

        if (showPosition !== 'card') {
            Object.assign(config, {
                categoryId: showPosition + '_' + config.categoryId,
                propertyData,
                enableCascade: true,
                parentPropertyID: 'editor',
                tabId: showPosition,
                tabName: '编辑器'
            });
        }
        return config;
    }


    /**
     * 列编辑器属性
     * @param gridFieldData 列数据
     */
    getGridFieldEdtiorPropConfig(gridFieldData: any, viewModelId: string) {
        const propertyData = gridFieldData.editor;

        this.propertyConfig = [];

        // 编辑器类型属性
        const editorTypeConfig = this.getGridFieldEditorTypePropertyConfig(gridFieldData, viewModelId);
        if (editorTypeConfig) {
            this.propertyConfig.push(editorTypeConfig);
        }

        // 外观属性
        const apperanceConfig = this.getAppearancePropConfig(propertyData, viewModelId, 'gridFieldEditor');
        this.propertyConfig.push(apperanceConfig);

        // 行为属性
        const behaviorConfig = this.getBehaviorPropConfig(propertyData, viewModelId, 'gridFieldEditor');
        this.appendBehaviorPropsForGridFieldEditor(behaviorConfig, propertyData, viewModelId);
        this.propertyConfig.push(behaviorConfig);

        // 事件属性
        const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId, 'gridFieldEditor');
        this.propertyConfig.push(eventPropConfig);

        return this.propertyConfig;

    }

    /**
     * table单元格编辑器属性
     * @param tdData 单元格数据
     * @param viewModelId viewModelId
     * @returns 属性配置
     */
    getTableTdEdtiorPropConfig(tdData: any, viewModelId: string): ElementPropertyConfig[] {
        const propertyData = tdData.editor;

        this.propertyConfig = [];

        // 外观属性
        const appearanceConfig = this.getAppearancePropConfig(propertyData, viewModelId, 'tableTdEditor');
        this.propertyConfig.push(appearanceConfig);

        // 行为属性
        const behaviorConfig = this.getBehaviorPropConfig(propertyData, viewModelId, 'tableTdEditor');
        behaviorConfig.properties = behaviorConfig.properties.filter(p => !'binding,visible'.includes(p.propertyID));
        this.propertyConfig.push(behaviorConfig);

        // 扩展区域属性
        const appendPropConfig = this.getInputAppendPropertyConfig(propertyData, viewModelId, 'tableTdEditor');
        this.propertyConfig.push(appendPropConfig);

        // 表达式属性
        const exprPropConfig = this.getExpressionPropConfig(propertyData, viewModelId, 'tableTdEditor');
        if (exprPropConfig) {
            this.propertyConfig.push(exprPropConfig);
        }

        // 事件属性
        const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId, 'tableTdEditor');
        this.propertyConfig.push(eventPropConfig);

        return this.propertyConfig;
    }
    /**
     * 国际化类型枚举项
     */
    private getLocalizationTypes(propertyData: any): KeyMap[] {
        switch (propertyData.fieldType) {
            case 'Date': {
                return [{ key: 'Date', value: '日期' }];
            }
            case 'DateTime': {
                return [{ key: 'DateTime', value: '日期时间' }];
            }
            default: {
                return [{ key: 'Date', value: '日期' }, { key: 'DateTime', value: '日期时间' }];
            }
        }
    }
    /**
     * 显示类型枚举项
     */
    private getShowTypeIterator(propertyData: any) {
        const showTypes = [
            { key: 1, value: '全部' },
            { key: 2, value: '显示年月' },
            { key: 3, value: '仅显示年' }
        ];
        if (propertyData.dateRange) {
            showTypes.push({ key: 4, value: '显示周' });
        }
        return showTypes;
    }

    /**
     * 日期格式化枚举项
     */
    private getDateFormatIteratror(propertyData: any): KeyMap[] {
        let formats = [];
        const { timeFormats, yMdFormats, yMFormats, mdFormats, yFormats } = DATE_FORMATS;

        switch (propertyData.showType) {
            // 年月
            case 2: {
                return yMFormats;
            }
            // 年
            case 3: {
                return yFormats;
            }
            // 全部
            case 1: {
                if (propertyData.showTime) {
                    formats = formats.concat(timeFormats);
                }
                formats = formats.concat(yMdFormats);
                formats = formats.concat(yMFormats);
                formats = formats.concat(yFormats);
                formats = formats.concat(mdFormats);

                break;
            }

            // 周
            case 4: {
                if (propertyData.showTime) {
                    formats = formats.concat(timeFormats);
                }
                formats = formats.concat(yMdFormats);
                formats = formats.concat(mdFormats);


                break;
            }
        }

        return formats;
    }
    /**
     * 存储格式枚举项
     */
    getReturnFormatIteratror(): KeyMap[] {

        return [
            { key: 'yyyy-MM-dd', value: 'yyyy-MM-dd' },
            { key: 'yyyy/MM/dd', value: 'yyyy/MM/dd' },
            { key: 'MM/dd/yyyy', value: 'MM/dd/yyyy' },
            { key: 'yyyy-MM-dd HH:mm:ss', value: 'yyyy-MM-dd HH:mm:ss' },
            { key: 'yyyy/MM/dd HH:mm:ss', value: 'yyyy/MM/dd HH:mm:ss' },
            { key: 'yyyyMM', value: 'yyyyMM' },
            { key: 'yyyy', value: 'yyyy' }
        ];

    }


}
